home *** CD-ROM | disk | FTP | other *** search
- /* TrackHilite.c */
- /*
- * Copyright © 1989 Martin Minow. All rights reserved.
- *
- * These routines invert the selection or draw insertion
- * point. When called, _TrackPtr points to the locked
- * TrackRecord. These routines are not called directly
- * by the application program.
- */
- #include "TrackEdit.h"
- #include "Color.h"
- #define TR (*tr)
- #define NIL 0
-
-
- static void invert_rect(
- TrackPtr, LONGINT, LONGINT, LONGINT);
-
- /*
- * _Track_hilite(track_ptr, start, end)
- * Invert the selection between start and end, both
- * given as indices into *(_TrackPtr->string). Note:
- * start is not necessarily "earlier" than end.
- */
- void
- _Track_hilite(tr, dot_start, dot_end)
- register TrackPtr tr;
- DOT dot_start;
- DOT dot_end;
- {
- LONGINT row_start, row_end;
- INTEGER col_start, col_end, start, end;
- DOT temp;
-
- /*
- * If there is no selection, there's nothing to
- * invert. Note that we're only called if the
- * window is active.
- */
- if (dot_start == dot_end)
- return; /* No hiliting needed */
- /*
- * It's a real selection: normalize the selection
- * so start is north-east of end and convert to
- * pixel coordinates.
- */
- if (dot_start > dot_end) {
- temp = dot_start;
- dot_start = dot_end;
- dot_end = temp;
- }
- row_start = _Track_row(tr, dot_start);
- row_end = _Track_row(tr, dot_end);
- col_start = _Track_dot_to_col(tr, dot_start);
- col_end = _Track_dot_to_col(tr, dot_end);
- /*
- * If everything is on one row, do it.
- */
- if (row_start == row_end)
- invert_rect(tr, row_start, col_start, col_end);
- else {
- /*
- * We have several lines to invert. Start with the
- * right end of the first line.
- */
- end = _Track_dot_to_eol(tr, row_start);
- invert_rect(tr, row_start, col_start, end);
- /*
- * Do any complete rows. This can be optimized
- * for many applications.
- */
- while (++row_start < row_end) {
- start = _Track_dot_to_bol(tr, row_start);
- end = _Track_dot_to_eol(tr, row_start);
- invert_rect(tr, row_start, start, end);
- }
- /*
- * Finally, do the last row.
- */
- start = _Track_dot_to_bol(tr, row_end);
- invert_rect(tr, row_end, start, col_end);
- }
- }
-
- /*
- * _Track_caret(track_ptr, desired_state)
- * Draw (or erase) the selection marker at selStart.
- * (Make sure it's in the mouse row.)
- * Call the user's caret routine if requested.
- */
- void
- _Track_caret(tr, state)
- register TrackPtr tr;
- INTEGER state;
- {
- /*
- * If there is a real selection, or the text is not
- * active, just return. Likewise if the caret state
- * shouldn't change. Otherwise, invert the caret.
- */
- if (!_Track_is_set(tr, _Track_is_active)
- || TR.selStart != TR.selEnd)
- ; /* No caret wanted */
- else if (state == _Track_caret_on
- && _Track_is_set(tr, _Track_caret_visible))
- ; /* Want on and it's still on */
- else if (state == _Track_caret_off
- && !_Track_is_set(tr, _Track_caret_visible))
- ; /* Want off and it's still off */
- else {
- /*
- * Invert the caret on screen.
- */
- _Track_flip(tr, _Track_caret_visible);
- _Track_invert_caret(tr);
- }
- }
-
- void
- _Track_invert_caret(tr)
- register TrackPtr tr;
- {
- PenState pen_state;
- Rect caret;
- LONGINT row;
- LONGINT col;
- DOT dot;
-
- if (TR.selStart != TR.selEnd)
- return;
- row = _Track_row(tr, TR.selStart);
- col = _Track_dot_to_col(tr, TR.selStart);
- if (col == TR.viewRect.left && TR.selRow < row) {
- /*
- * Hack: if dot is at the start of a line, the true
- * mouse point might be at the end of the previous
- * line. In this case, the mouse row won't equal
- * dot's row. Force the caret point so it's to
- * the right of the last character on the previous
- * row.
- * Further hack, if selStart is at the end of the
- * text, look at the last character. If it's
- * a <return>, caret is really on the next line.
- * Grumble.
- */
- if (TR.selStart != (DOT) TR.textLength
- || TR.textLength == 0
- || (*TR.hText)[TR.selStart - 1] != '\r') {
- row = TR.selRow;
- col = _Track_dot_to_col(tr, TR.selStart - 1)
- + CharWidth((*TR.hText)[TR.selStart - 1]);
- }
- }
- /*
- * Convert to the equivalent pixel coordinate and
- * draw it if it might be visible.
- */
- row = _Track_row_pixel(tr, row);
- if (row < (LONGINT) TR.viewRect.top - TR.lineHeight
- || row > (LONGINT) TR.viewRect.bottom + TR.lineHeight
- || col < (LONGINT) TR.viewRect.left
- || col > (LONGINT) TR.viewRect.right)
- return; /* Invisible */
- if (TR.caretHook != NIL) {
- SetRect(
- &caret,
- (int) col,
- (int) row - TR.fontAscent,
- (int) col + 1,
- (int) row + TR.fontDescent
- );
- CallPascal(&caret, tr, TR.caretHook);
- }
- else {
- /*
- * Fancy "caret."
- */
- GetPenState(&pen_state);
- PenNormal();
- PenMode(patXor);
- MoveTo(col, (int) row - TR.fontAscent);
- Line(0, TR.fontAscent);
- Line(-TR.fontDescent, TR.fontDescent);
- Move(TR.fontDescent * 2, 0);
- Line(-TR.fontDescent, -TR.fontDescent);
- SetPenState(&pen_state);
- }
- }
-
- /*
- * invert_rect(tr, row, start, end)
- * Invert the screen rectangle on the specified row
- * between the specified horizontal pixels.
- * Note: end points just to the right of the last pixel
- * to invert. Also, note that this routine understands
- * that points are normalized, extending them in the
- * appropriate direction to cover the character.
- */
- static void
- invert_rect(tr, row, start, end)
- register TrackPtr tr;
- LONGINT row;
- LONGINT start;
- LONGINT end;
- {
- Rect box;
-
- /*
- * Convert row to the equivalent pixel coordinate.
- */
- row = _Track_row_pixel(tr, row);
- if (start == end
- || row < (LONGINT) TR.viewRect.top - TR.lineHeight
- || row > (LONGINT) TR.viewRect.bottom + TR.lineHeight)
- return;
- if (start < (LONGINT) TR.viewRect.left)
- start = (LONGINT) TR.viewRect.left;
- if (end > (LONGINT) TR.viewRect.right)
- end = (LONGINT) TR.viewRect.right;
- if (start >= end)
- return;
- box.left = (int) start;
- box.right = (int) end;
- box.top = (int) row + TR.fontDescent - TR.lineHeight;
- box.bottom = (int) row + TR.fontDescent;
- if (SectRect(&box, &TR.viewRect, &box)) {
- if (TR.highHook != NIL) /* Use user's */
- CallPascal(&box, tr, TR.highHook); /* hiliter */
- else {
- /*
- * Properly hilite color screens (ok for b/w, too)
- * See Inside Mac V, p. 62.
- */
- HiliteMode &= ~(1 << hiliteBit);
- InvertRect(&box);
- }
- }
- }
-
-